package co.com.siti.sie.managedbean.data;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;

import co.com.siti.sie.model.Tblannoperiodo;
import co.com.siti.sie.model.Tblciclo;
import co.com.siti.sie.model.Tblciclogradoasignatura;
import co.com.siti.sie.model.Tblclaseid;
import co.com.siti.sie.model.Tblevaluacionasignatura;
import co.com.siti.sie.model.Tblgrado;
import co.com.siti.sie.model.Tblgrupo;
import co.com.siti.sie.model.Tbljornada;
import co.com.siti.sie.model.Tblmatriculaalumno;
import co.com.siti.sie.model.Tblsede;
import co.com.siti.sie.model.Vwalumnomatricula;
import co.com.siti.sie.util.Parametros;
import co.com.siti.sie.vo.AlumnoVO;
import co.com.siti.sie.vo.AnnoPeriodoVO;
import co.com.siti.sie.vo.AsignaturaVO;
import co.com.siti.sie.vo.CicloVO;
import co.com.siti.sie.vo.GradoVO;
import co.com.siti.sie.vo.GrupoVO;
import co.com.siti.sie.vo.JornadaVO;
import co.com.siti.sie.vo.SedeVO;
import co.com.siti.sie.vo.TipoDocVO;
import co.com.siti.sie.vo.VwProGusAsigAlumDTO;

public class TrasladosDataManagedBean {

	private static final String PERSISTENCE_UNIT_NAME = Parametros._UNIDADPERSISTENCIA;
	private static EntityManagerFactory factory;

	public static List<SedeVO> getSedes() {
		List<SedeVO> retorno = new ArrayList<SedeVO>();
		factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
		EntityManager em = factory.createEntityManager();
		Query q = em.createNamedQuery("Tblsede.findAll");
		List<Tblsede> sedes = q.getResultList();
		em.close();

		if (sedes != null && !sedes.isEmpty()) {
			for (Tblsede sede : sedes) {
				retorno.add(new SedeVO(sede.getFldidsede(), sede
						.getNombreSede()));
			}
		}

		return retorno;
	}

	public static List<JornadaVO> getJornadas() {
		List<JornadaVO> retorno = new ArrayList<JornadaVO>();
		factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
		EntityManager em = factory.createEntityManager();
		Query q = em.createNamedQuery("Tbljornada.findAll");
		List<Tbljornada> jornadas = q.getResultList();
		em.close();

		if (jornadas != null && !jornadas.isEmpty()) {
			for (Tbljornada jornada : jornadas) {
				retorno.add(new JornadaVO(jornada.getCodJornada(), jornada
						.getDescripcionJornada()));
			}
		}

		return retorno;
	}

	public static List<CicloVO> getCiclos() {
		List<CicloVO> retorno = new ArrayList<CicloVO>();
		factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
		EntityManager em = factory.createEntityManager();
		Query q = em.createNamedQuery("Tblciclo.findAll");
		List<Tblciclo> ciclos = q.getResultList();
		em.close();

		if (ciclos != null && !ciclos.isEmpty()) {
			for (Tblciclo ciclo : ciclos) {
				retorno.add(new CicloVO(ciclo.getCodCiclo(), ciclo
						.getDescripcionCiclo()));
			}
		}

		return retorno;
	}

	public static List<GradoVO> getGrados(String ciclo) {
		System.out.println("ciclo: " + ciclo);
		List<GradoVO> retorno = new ArrayList<GradoVO>();
		factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
		EntityManager em = factory.createEntityManager();
		Query q = em.createNamedQuery("Tblgrado.findAllByCiclo").setParameter(
				"ciclo", Integer.parseInt(ciclo));
		List<Tblgrado> grados = q.getResultList();
		em.close();

		if (grados != null && !grados.isEmpty()) {
			for (Tblgrado grado : grados) {
				retorno.add(new GradoVO(grado.getLlaveGrado(), grado
						.getDescripcionGrado()));
			}
		}

		return retorno;
	}

	public static List<GrupoVO> getGrupos(String idSede, String idJornada,
			String cicloGrado) {
		System.out.println("idSede: " + idSede + ", idJornada: " + idJornada
				+ ", cicloGrado: " + cicloGrado);
		List<GrupoVO> retorno = new ArrayList<GrupoVO>();
		factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
		EntityManager em = factory.createEntityManager();
		Query q = em.createNamedQuery("Tblgrupo.findGrupoConCondiciones")
				.setParameter("sede", Integer.parseInt(idSede))
				.setParameter("jornada", Integer.parseInt(idJornada))
				.setParameter("cicloGrado", Integer.parseInt(cicloGrado));
		List<Tblgrupo> grupos = q.getResultList();
		em.close();

		if (grupos != null && !grupos.isEmpty()) {
			for (Tblgrupo grupo : grupos) {
				retorno.add(new GrupoVO(grupo.getFldllavegrupo(), grupo
						.getFlddescripcion()));
			}
		}

		return retorno;
	}

	public static List<AlumnoVO> getAlumnos(String grupoSeleccionado,
			Integer annoLectivo) {
		System.out.println("grupoSeleccionado: " + grupoSeleccionado
				+ ", annoLectivo: " + annoLectivo);
		List<AlumnoVO> retorno = new ArrayList<AlumnoVO>();
		factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
		EntityManager em = factory.createEntityManager();
		Query q = em.createNamedQuery("Vwalumnomatricula.findByGrupo")
				.setParameter("grupo", Integer.parseInt(grupoSeleccionado))
				.setParameter("anno", annoLectivo);
		List<Vwalumnomatricula> matriculas = q.getResultList();
		em.close();

		if (matriculas != null && !matriculas.isEmpty()) {
			for (Vwalumnomatricula matricula : matriculas) {
				// TODO el estado del alumno no sale de la vista, de donde se
				// debe tomar?
				retorno.add(new AlumnoVO(matricula.getLlavematricula()
						.toString(), matricula.getIdllavealumno().toString(),
						matricula.getSigla() + " " + matricula.getFldnrodoc(),
						matricula.getNombre(), true));
			}
		}

		return retorno;
	}

	public static AnnoPeriodoVO getAnnoLectivo() {
		AnnoPeriodoVO retorno = null;
		factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
		EntityManager em = factory.createEntityManager();
		Query q = em.createNamedQuery("Tblannoperiodo.findPeridoActivo");
		Tblannoperiodo periodo = (Tblannoperiodo) q.getSingleResult();
		em.close();

		if (periodo != null) {
			retorno = new AnnoPeriodoVO(periodo.getFldidannoper(), periodo
					.getFldanno().toString());
		}

		return retorno;
	}

	public static void realizarTraslado(List<AlumnoVO> alumnos,
			String grupoTraslado) {
		System.out.println("alumnos: " + alumnos + ", grupoTraslado: "
				+ grupoTraslado);
		factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
		EntityManager em = factory.createEntityManager();
		Query q = em.createNamedQuery("Tblmatriculaalumno.findById");
		for (AlumnoVO alumno : alumnos) {
			System.out.println("alumno: " + alumno);
			q.setParameter("id", Integer.parseInt(alumno.getIdMatricula()));
			Tblmatriculaalumno matricula = (Tblmatriculaalumno) q
					.getSingleResult();
			System.out.println("inicio transaccion traslado");
			em.getTransaction().begin();
			matricula.setFldidgrupo(Integer.parseInt(grupoTraslado));
			em.getTransaction().commit();
			System.out.println("fin transaccion traslado");
		}
	}

	public static List<TipoDocVO> getTiposDocumentos() {
		List<TipoDocVO> retorno = new ArrayList<TipoDocVO>();
		factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
		EntityManager em = factory.createEntityManager();
		Query q = em.createNamedQuery("Tblclaseid.findAll");
		List<Tblclaseid> tipos = q.getResultList();
		em.close();

		if (tipos != null && !tipos.isEmpty()) {
			for (Tblclaseid tipo : tipos) {
				retorno.add(new TipoDocVO(tipo.getCodClId(), tipo.getSigla()));
			}
		}

		return retorno;
	}

	/**
	 * @param numdocProfesor
	 * @return
	 */
	public static List<GrupoVO> getGruposNotasProsefor(String numdocProfesor) {
		List<GrupoVO> retorno;
		List<VwProGusAsigAlumDTO> resultados = new ArrayList<VwProGusAsigAlumDTO>();
		Map<Integer, GrupoVO> mapaGrupos = new HashMap<Integer, GrupoVO>();
		factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
		EntityManager em = factory.createEntityManager();
		Query q = em
				.createNativeQuery(
						"select * from (select peri.fldanno, peri.fldperiodo, pro.fldidprofesor codigo_profesor,cl_id_profesor tipodoc_profesor, id_profesor numdoc_profesor, primer_nombre_profesor||' '||segundo_nombre_profesor||' '||primer_apellido_profesor||' '||segdo_apellido_profesor nombre_profesor,gru.fldllavegrupo codigo_grupo, flddescripcion nombre_grupo, fldllave codigo_asignatura, fldnombre nombre_asignatura, alu.fldidllavealumno codigo_alumno, tipo_id_alumno tipodoc_alumno,id_alumno numdoc_alumno, primer_nombre_alumno||' '||segundo_nombre_alumno||' '||primer_apellido_alumno||' '||segundo_apellido_alumno nombre_alumno,eva.fldidcodigoevindicador idcalificacion, eva.fldcalificacion calificacion, gru.fldidciclogrado ciclo_grado_asigna from tblannoperiodo peri join tblasignaxprofesor axp on axp.fldanolectivo = peri.fldanno join tblprofesor pro on axp.fldidprofesor=pro.fldidprofesor join tblasignaturas asi on axp.fldidasignatura=asi.fldllave join tblgrupo gru on axp.fldidgrupo=gru.fldllavegrupo join tblmatriculaalumno matri on matri.fldidanno = peri.fldanno and gru.fldllavegrupo=matri.fldidgrupo join tblalumno alu on matri.fldidllavealumno=alu.fldidllavealumno join tblciclogradoasignatura cga on cga.fldidciclogrado=gru.fldidciclogrado and cga.fldidasignatura=asi.fldllave left join tblevaluacionasignatura eva on eva.fldanno=peri.fldanno and eva.fldperiodo=peri.fldperiodo and eva.fldidllavealumno=alu.fldidllavealumno and eva.fldidciclogradoasigna=cga.fldidrelacion and eva.fldidprofesor=pro.fldidprofesor and eva.fldidgrupo=gru.fldllavegrupo where peri.fldestado=1 and cga.fldidestado=1) resul where numdoc_profesor = ? order by codigo_profesor,nombre_grupo,nombre_asignatura,nombre_alumno")
				.setParameter(1, numdocProfesor);
		List<Object[]> aux = q.getResultList();
		em.close();

		if (aux != null && !aux.isEmpty()) {

			System.out.println("registros encontrados: " + aux.size());

			for (Object[] resultado : aux) {
				resultados
						.add(new VwProGusAsigAlumDTO(
								(Integer) resultado[0],
								(Integer) resultado[1],
								(Integer) resultado[2],
								(Integer) resultado[3],
								(String) resultado[4],
								(String) resultado[5],
								(Integer) resultado[6],
								(String) resultado[7],
								(Integer) resultado[8],
								(String) resultado[9],
								(Integer) resultado[10],
								(Integer) resultado[11],
								(String) resultado[12],
								(String) resultado[13],
								resultado[14] != null ? (Integer) resultado[14]
										: null,
								resultado[15] != null ? (Double) resultado[15]
										: null,
								resultado[16] != new Double(0) ? (Integer) resultado[16]
										: null));
			}

			for (VwProGusAsigAlumDTO resultado : resultados) {

				// se busca si el grupo no existe en el mapa
				if (!mapaGrupos.containsKey(resultado.getCodigoGrupo())) {
					System.out.println("nuevo grupo encontrado: "
							+ resultado.getCodigoGrupo());
					// se crea el grupo de no existir
					GrupoVO grupoNuevo = new GrupoVO(
							resultado.getCodigoGrupo(),
							resultado.getNombreGrupo());
					// se crea el listado vacio de asignaturas del grupo
					grupoNuevo.setAsignaturas(new ArrayList<AsignaturaVO>());
					// se asigna al mapa
					mapaGrupos.put(resultado.getCodigoGrupo(), grupoNuevo);
				}

				boolean existeAsignatura = false;
				for (AsignaturaVO asignatura : mapaGrupos.get(
						resultado.getCodigoGrupo()).getAsignaturas()) {
					if (asignatura.getCodigo().equals(
							resultado.getCodigoAsignatura())) {
						existeAsignatura = true;
						asignatura.getAlumnos().add(
								new AlumnoVO(null, resultado.getCodigoAlumno()
										.toString(), resultado
										.getNumdocAlumno(), resultado
										.getNombreAlumno(), true, resultado
										.getIdcalificacion(), resultado
										.getCalificacion()));
						break;
					}
				}

				if (!existeAsignatura) {
					System.out.println("nueva asignatura encontrada: "
							+ resultado.getCodigoAsignatura() + " - grupo: "
							+ resultado.getCodigoGrupo());
					AsignaturaVO asignaturaNueva = new AsignaturaVO(
							resultado.getCodigoAsignatura(),
							resultado.getNombreAsignatura());
					asignaturaNueva.setCicloGradoAsignatura(resultado
							.getCicloGradoAsigna());
					asignaturaNueva.setAlumnos(new ArrayList<AlumnoVO>());
					asignaturaNueva.getAlumnos().add(
							new AlumnoVO(null, resultado.getCodigoAlumno()
									.toString(), resultado.getNumdocAlumno(),
									resultado.getNombreAlumno(), true,
									resultado.getIdcalificacion(), resultado
											.getCalificacion()));
					mapaGrupos.get(resultado.getCodigoGrupo()).getAsignaturas()
							.add(asignaturaNueva);
				}

			}

		}

		System.out.println("grupos encontrados: " + mapaGrupos.size());
		for (GrupoVO gru : mapaGrupos.values()) {
			System.out.println("grupo: " + gru.getCodigo() + ", asignaturas: "
					+ gru.getAsignaturas().size());
			for (AsignaturaVO asi : gru.getAsignaturas()) {
				System.out.println("asignatura: " + asi.getCodigo()
						+ ", alumnos: " + asi.getAlumnos().size());
			}
		}

		retorno = new ArrayList<GrupoVO>(mapaGrupos.values());

		return retorno;
	}

	public static void actualizarCalificacion(Integer idNota,
			Double calificacion) {
		System.out.println("idNota: " + idNota + ", calificacion: "
				+ calificacion);
		factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
		EntityManager em = factory.createEntityManager();
		Query q = em.createNamedQuery("Tblevaluacionasignatura.findById")
				.setParameter("id", idNota);

		Tblevaluacionasignatura evaluacion = (Tblevaluacionasignatura) q
				.getSingleResult();

		System.out.println("inicio actualización calificacion");
		em.getTransaction().begin();
		evaluacion.setFldcalificacion(calificacion);
		;
		em.getTransaction().commit();
		System.out.println("fin actualización calificacion");
	}

	public static void crearCicloGradoAsignatura(GrupoVO grupo,
			AsignaturaVO asignatura, AlumnoVO alumno, Double calificacion,
			String usuario, Integer idProfesor) {
		EntityManager em = factory.createEntityManager();
		System.out.println("inicio consulta ciclo grado asignatura");
		
		Query q = em.createNamedQuery("Tblciclogradoasignatura.findAll")
				.setParameter("ciclogrado", asignatura.getCicloGradoAsignatura()).setParameter("asignatura", asignatura.getCodigo());

		Tblciclogradoasignatura reg = (Tblciclogradoasignatura) q
				.getSingleResult();
		
		System.out.println("fin consulta ciclo grado asignatura");

		System.out.println("ID: " + reg.getFldidrelacion());

		q = em.createNamedQuery("Tblannoperiodo.findPeridoActivo");
		Tblannoperiodo periodo = (Tblannoperiodo) q.getSingleResult();

		Tblevaluacionasignatura eva = new Tblevaluacionasignatura();
		eva.setFldanno(periodo.getFldanno());
		eva.setFldperiodo(periodo.getFldperiodo());
		eva.setFldidllavealumno(Integer.parseInt(alumno.getCodigo()));
		eva.setFldidciclogradoasigna(reg.getFldidrelacion());
		eva.setFldidtipoevaluacion(1);
		eva.setFldidprofesor(idProfesor);
		eva.setFldnrofallas(0);
		eva.setFldcalificacion(calificacion);
		eva.setFldrecupera(0);
		eva.setFldidgrupo(grupo.getCodigo());
		eva.setFldusuario(usuario);
		eva.setFldfchgrabacion(Calendar.getInstance().getTime());

		System.out.println("inicio inserción calificacion");
		em.getTransaction().begin();
		em.persist(eva);
		em.getTransaction().commit();
		System.out.println("fin inserción calificacion");

		System.out.println("ID: " + eva.getFldidcodigoevindicador());

	}

}
